﻿using log4net;
using System.Data;
using System.Reflection;
using Koala.Pro.CodeGenerator.UI.Common;

namespace Koala.Pro.CodeGenerator.UI.DatabaseModel.Schema
{
    public class DatabaseInfo
    {
        public delegate string GetTableNameAliasConverterHandler(string tableName, string dbType);

        public delegate string GetColumnNameAliasConverterHandler(string tableName, string columnName, string dbType);

        private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        private NameElement name;

        private IDictionary<string, TableInfo> tableList = new Dictionary<string, TableInfo>();

        private IDictionary<string, ViewInfo> viewList = new Dictionary<string, ViewInfo>();

        private IDictionary<string, ProcedureInfo> procedureList = new Dictionary<string, ProcedureInfo>();

        private DbInstanceInfo _db;

        public GetColumnNameAliasConverterHandler ColumnAliasHandler;

        public GetTableNameAliasConverterHandler TableAliasHandler;

        public NameElement Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        public IDictionary<string, TableInfo> TableList
        {
            get
            {
                return tableList;
            }
            set
            {
                tableList = value;
            }
        }

        public IDictionary<string, ViewInfo> ViewList
        {
            get
            {
                return viewList;
            }
            set
            {
                viewList = value;
            }
        }

        public IDictionary<string, ProcedureInfo> ProcedureList
        {
            get
            {
                return procedureList;
            }
            set
            {
                procedureList = value;
            }
        }

        public DbInstanceInfo db
        {
            get
            {
                return _db;
            }
            set
            {
                _db = value;
            }
        }

        public IDictionary<string, TableInfo> ListTables()
        {
            string database = Name.Name.ToString();
            log.Debug($"database={database}");
            TableList = db.DatabaseAssembly.ListTables(database);
            foreach (TableInfo value in TableList.Values)
            {
                value.DatabaseInfo = this;
                log.Debug("======获取表名的别名======");
                log.DebugFormat("Name:{0}, DatabaseType:{1}", value.Name.Name.ToString(), db.DatabaseType);
               
                if (value.DatabaseInfo.TableAliasHandler == null)
                {
                    value.DatabaseInfo.TableAliasHandler = GetTableAlias;
                }  

                string text = value.DatabaseInfo.TableAliasHandler(value.Name.Name.ToString(), db.DatabaseType);
                if (!string.IsNullOrEmpty(text))
                {
                    value.Name.Alias = new CString(text);
                    log.DebugFormat("Table {0} Alias is:{1}", value.Name, text);
                }
                value.ListColumns();
            }
            return TableList;
        }

        public static string GetTableAlias(string tableName, string databaseType)
        {
            string result = string.Empty;
            try
            {
                TableNameAliasInfo tableNameAliasInfo = TableNameAliasInfo.GetAliasByName(tableName, databaseType);
                if (tableNameAliasInfo != null && !string.IsNullOrEmpty(tableNameAliasInfo.TableAlias))
                {
                    result = tableNameAliasInfo.TableAlias;
                }
            }
            catch (Exception exception)
            {
                log.Error("Error when invokes GetAliasName", exception);
                throw;
            }
            return result;
        }

        public IDictionary<string, ViewInfo> ListViews()
        {
            string database = Name.Name.ToString();
            ViewList = _db.DatabaseAssembly.ListViews(database);
            foreach (KeyValuePair<string, ViewInfo> view in ViewList)
            {
                view.Value.ParentDatabase = this;
            }
            return ViewList;
        }

        public IDictionary<string, ProcedureInfo> ListProcedures()
        {
            string database = Name.Name.ToString();
            ProcedureList = db.DatabaseAssembly.ListProcedures(database);
            foreach (KeyValuePair<string, ProcedureInfo> procedure in ProcedureList)
            {
                procedure.Value.ParentDatabase = this;
            }
            return ProcedureList;
        }

        public DataSet ExecuteSql(string query)
        {
            string database = Name.Name.ToString();
            return db.DatabaseAssembly.ExecuteSql(database, query);
        }

        public override string ToString()
        {
            return StringUtil.ToString(this);
        }
    }

}
